package com.example.forum.service.impl;

import com.example.forum.dao.LoginTicketDao;
import com.example.forum.dao.UserDao;
import com.example.forum.domain.LoginTicket;
import com.example.forum.domain.User;
import com.example.forum.service.UserService;
import com.example.forum.utils.ActiveStatus;
import com.example.forum.utils.HostHolder;
import com.example.forum.utils.MailUtils;
import com.example.forum.utils.SimpleUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

@Service
public class UserServiceImpl implements UserService, ActiveStatus {
    @Autowired
    private UserDao userDao;
    @Autowired
    private LoginTicketDao loginTicketDao;
    @Autowired
    private MailUtils mailUtils;
    @Autowired
    private TemplateEngine templateEngine;
    @Value("${forum.path.domain}")
    private String domain;
    @Value("${server.servlet.context-path}")
    private String contextPath;
    @Autowired
    private HostHolder hostHolder;

    @Override
    public User findById(Integer id) {
        return userDao.findById(id);
    }

    @Override
    public Map<String,String> registerUser(User user)  {
        Map<String,String> map=new HashMap<>();
        if(user==null){
            map.put("parameterMsg","参数不能为空");
            return map;
        }
        if(StringUtils.isBlank(user.getUsername())){
            map.put("usernameMsg","用户名不能为空");
            return map;
        }
        if(StringUtils.isBlank(user.getPassword())){
            map.put("passwordMsg","密码不能为空");
            return map;
        }
        if(StringUtils.isBlank(user.getEmail())){
            map.put("emailMsg","邮箱不能为空");
            return map;
        }
        //判断用户名是否存在
        User byUsername = userDao.findByUsername(user.getUsername());
        if(byUsername!=null){
            map.put("usernameExit","该用户名已经被使用");
            return map;
        }
        //判断邮箱是否被使用
        User byEmail = userDao.findByEmail(user.getEmail());
        if(byEmail!=null){
            map.put("emailExit","该邮箱已经被注册");
            return map;
        }
        //用随机5个字符当做用户的盐值
        user.setSalt(SimpleUtils.generateUuid().substring(0,5));
        //将用户密码进行MD5盐值加密
        user.setPassword(SimpleUtils.MD5(user.getPassword()+user.getSalt()));
        //设置用户头像
        user.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png",new Random().nextInt(1000)));
        //设置用户类型为0代表普通用户
        user.setType(0);
        //设置用户状态为0代表未激活
        user.setStatus(0);
        //设置用户激活码
        user.setActivationCode(SimpleUtils.generateUuid());
        //设置创建时间
        user.setCreateTime(new Date());
        //注册用户
        userDao.register(user);
        //查询当前注册用户的id
        int id=userDao.findByUsername(user.getUsername()).getId();
        //根用户发送激活邮件
        Context context=new Context();
        context.setVariable("username",user.getUsername());
        context.setVariable("email",user.getEmail());
        context.setVariable("location",domain+contextPath+"active"+"?activeCode="+user.getActivationCode()
                +"&id="+id);
        //生成动态邮件
        String process = templateEngine.process("/mail/activation",context);
        //发送邮件
        mailUtils.sendMail(user.getEmail(),"牛客网激活邮件",process);
        //注册成功返回null
        return null;
    }

    @Override
    public int active(String activeCode,int id) {
        User user = userDao.findById(id);
        if(user.getStatus()==1){    //用户已经激活过
            return ACTIVE_REPEAT;
        }
        //用户没有激活
        if(user.getActivationCode().equals(activeCode)){
            //将用户激活
            userDao.active(activeCode,id);
            return ACTIVE_SUCCESS;
        }
        //激活失败
        return ACTIVE_FAIL;
    }

    @Override
    public Map<String, Object> login(String username, String password,int timeoutSeconds) {
        Map<String,Object> map=new HashMap<>();
        if(StringUtils.isBlank(username)){
            map.put("usernameMsg","用户名不能为空");
            return map;
        }
        if(StringUtils.isBlank(password)){
            map.put("passwordMsg","密码不能为空");
            return map;
        }
        User user = userDao.findByUsername(username);
        if(user==null){
            map.put("usernameExit","该账号不存在");
            return map;
        }
        if(!user.getPassword().equals(SimpleUtils.MD5(password+user.getSalt()))){
            map.put("passwordError","用户名或密码错误");
            return map;
        }
        if(user.getStatus()==0){
            map.put("lock","该账号没有激活,无法使用");
            return map;
        }
        //登录成功后生成登录凭证
        LoginTicket loginTicket=new LoginTicket();
        loginTicket.setUserId(user.getId());
        loginTicket.setTicket(SimpleUtils.generateUuid());
        loginTicket.setStatus(0);
        //设置超时时间
        loginTicket.setExpired(new Date(System.currentTimeMillis()+1000*timeoutSeconds));
        loginTicketDao.addLoginTicket(loginTicket);
        map.put("ticket",loginTicket);
        //登录成功返回null
        return map;
    }

    @Override
    public void upHeadImage(String headerUrl,int id) {
        userDao.upHeaderImage(headerUrl,id);
    }

    @Override
    public Map<String,String> updatePassword(String oldPassword,String newPassword,String confirmPassword) {
        Map<String,String> map=new HashMap<>();
        if(oldPassword==null){
            map.put("oldError","原密码不能为空");
            return map;
        }
        if(newPassword==null || confirmPassword==null){
            map.put("newError","新密码不能为空");
            return map;
        }
        if(!newPassword.equals(confirmPassword)){
            map.put("newError","两次输入的密码不一致");
            return map;
        }
        //查询旧密码是否正确
        User user = hostHolder.getUser();
        if (user.getPassword().equals(SimpleUtils.MD5(oldPassword+user.getSalt()))){ //旧密码正确
            //修改密码
            userDao.updatePassword(user.getId(),SimpleUtils.MD5(newPassword+user.getSalt()));
            return map;
        }
        //旧密码不正确
        map.put("oldError","原密码输入错误");
        return map;
    }
}
